/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package snmpapplication.snmp;

import java.util.ArrayList;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import snmpapplication.Main;
import snmpapplication.log.Severity;
import snmpapplication.utils.Constante;
import snmpapplication.utils.InterfaceType;

/**
 *
 * @author APetcu
 */
public class SnmpClientGetMultiple {

    private PDU createInterfacePDU(int count) {
        PDU requestPDU;
        requestPDU = new PDU();
        requestPDU.add(new VariableBinding(new OID(Constante.OIDifIndex + count)));
        requestPDU.add(new VariableBinding(new OID(Constante.OIDifDescr + count)));
        requestPDU.add(new VariableBinding(new OID(Constante.OIDifType + count)));
        requestPDU.add(new VariableBinding(new OID(Constante.OIDifSpeed + count)));
        requestPDU.add(new VariableBinding(new OID(Constante.OIDifPhysAddress + count)));
        requestPDU.add(new VariableBinding(new OID(Constante.OIDifAdminStatus + count)));
        requestPDU.add(new VariableBinding(new OID(Constante.OIDifOperStatus + count)));

        requestPDU.setType(PDU.GETNEXT);
        return requestPDU;
    }

    public ArrayList<ArrayList<String>> performSNMPInterfaceCheck(String host, String community, int interfaceCount) {

        ArrayList<ArrayList<String>> fin = new ArrayList<ArrayList<String>>();

        try {
            CommunityTarget comtarget = new CommunityTarget();
            OctetString community1 = new OctetString(community);
            host = host + "/" + "161";
            Address tHost = new UdpAddress(host);
            Snmp snmp;

            comtarget.setCommunity(community1);
            comtarget.setVersion(SnmpConstants.version1);
            comtarget.setAddress(tHost);
            comtarget.setRetries(2);
            comtarget.setTimeout(3000);

            TransportMapping transport;
            transport = new DefaultUdpTransportMapping();
            transport.listen();
            snmp = new Snmp(transport);

            for (int i = 0; i < interfaceCount; i++) {

                ArrayList<String> temp = new ArrayList<String>();

                PDU requestPDU = createInterfacePDU(i);

                ResponseEvent response = snmp.send(requestPDU, comtarget);
                if (response.getResponse() == null) {
                    Main.log.log(new Severity(Severity.SEV_HIG), "NULL response from host");
                    continue;
                } else {
                    VariableBinding[] array = response.getResponse().toArray();

                    for (VariableBinding variableBinding : array) {
                        String value = variableBinding.getVariable().toString();
                        String key = variableBinding.getOid().toString();

                        if (key.startsWith(Constante.OIDifIndex)) {
                            temp.add(value);
                        }

                        if (key.startsWith(Constante.OIDifDescr)) {
                            String ifDescription = value;
                            String[] split = value.split(":");
                            if (split.length > 1) {
                                StringBuffer buffer = new StringBuffer();
                                try {
                                    for (String string : split) {
                                        int parseInt = Integer.parseInt(string, 16);
                                        buffer.append(Character.toChars(parseInt));
                                    }
                                } catch (NumberFormatException exception) {
                                    //System.out.println("Exception for if description - error - " + exception.getMessage());
                                    Main.log.log(new Severity(Severity.SEV_INFO), "Exception for description:" + exception.getMessage());
                                    buffer = new StringBuffer(value);
                                }
                                ifDescription = buffer.toString();
                            }
                            temp.add(ifDescription);
                        } else if (key.startsWith(Constante.OIDifType)) {
                            if (value != null) {
                                temp.add(InterfaceType.determineInterfaceType(Integer.parseInt(value)));
                            }
                        } else if (key.startsWith(Constante.OIDifSpeed)) {
                            if (value != null) {
                                long speedValue = Long.parseLong(value);
                                speedValue = speedValue / (1000 * 1000);
                                temp.add(Long.toString(speedValue));
                            }
                        } else if (key.startsWith(Constante.OIDifPhysAddress)) {

                            if (value != null) {
                                String[] split = value.trim().split(" ");
                                if (split.length < 1) {
                                    StringBuilder buffer = new StringBuilder();
                                    for (i = 0; i < split.length; i++) {
                                        buffer.append(split[i].equals(" ")
                                                ? "-" : split[i]);
                                    }
                                    value = buffer.toString();
                                }
                            }
                            temp.add(value.toUpperCase());
                        } else if (key.startsWith(Constante.OIDifAdminStatus)) {
                            if (value != null) {
                                int adminStatus = Integer.parseInt(value);
                                switch (adminStatus) {

                                    case 1:
                                        temp.add("UP");
                                        break;
                                    case 2:
                                        temp.add("DOWN");
                                        break;
                                    case 3:
                                        temp.add("TESTING");
                                        break;

                                }
                            }
                        } else if (key.startsWith(Constante.OIDifOperStatus)) {
                            if (value != null) {
                                int operStatus = Integer.parseInt(value);
                                switch (operStatus) {

                                    case 1:
                                        temp.add("up");
                                        break;
                                    case 2:
                                        temp.add("down");
                                        break;
                                    case 3:
                                        temp.add("testing");
                                        break;
                                }
                            }
                        }
                    }
                }
                fin.add(temp);
            }
        } catch (Exception exception) {
            //System.out.println("Unable to perform snmp interface search  -error - " + exception.getMessage());
            Main.log.log(new Severity(Severity.SEV_ERR), "Exception at SNMP SET:" + exception.getMessage());
        }

        return fin;
    }
}
